package com.banmoon.collection;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 使用多个Condition实现精准唤醒
 */
public class Demo6 {

    public static void main(String[] args) {
        MyDemo6 myDemo4 = new MyDemo6();
        new Thread(() -> {
            for(int i = 0; i < 10; i++) myDemo4.increment();
        }, "线程A").start();
        new Thread(() -> {
            for(int i = 0; i < 10; i++) myDemo4.decrement();
        }, "线程B").start();
        new Thread(() -> {
            for(int i = 0; i < 10; i++) myDemo4.increment();
        }, "线程C").start();
        new Thread(() -> {
            for(int i = 0; i < 10; i++) myDemo4.decrement();
        }, "线程D").start();
    }
}

class MyDemo6 {

    private int number = 0;

    private Lock lock = new ReentrantLock(true);

    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    private Condition condition4 = lock.newCondition();

    public void increment(){
        lock.lock();
        try {
            while (number==1)
                await();
            number++;
            System.out.println(Thread.currentThread().getName() + "：" + number);
            signal();
        }  finally {
            lock.unlock();
        }
    }

    public void decrement(){
        lock.lock();
        try {
            while (number==0)
                await();
            number--;
            System.out.println(Thread.currentThread().getName() + "：" + number);
            signal();
        }  finally {
            lock.unlock();
        }
    }

    /**
     * 判断当前线程，并触发等待
     */
    public void await(){
        try {
            String name = Thread.currentThread().getName();
            switch (name){
                case "线程A": condition1.await(); break;
                case "线程B": condition2.await(); break;
                case "线程C": condition3.await(); break;
                case "线程D": condition4.await(); break;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 判断当前线程，并触发唤醒
     */
    public void signal(){
        String name = Thread.currentThread().getName();
        switch (name){
            case "线程A": condition2.signal(); break;
            case "线程B": condition3.signal(); break;
            case "线程C": condition4.signal(); break;
            case "线程D": condition1.signal(); break;
        }
    }

}